//! Handling for player input.

use craftdig_math::Vec3f;

use godot::{classes::Input, obj::Gd};

const MOVE_ACTIVATION_THRESH: f32 = 0.01;

/// Actual inputs captured on each frame.
pub struct InputState {
    /// If just attacked (left click).
    pub attacked: bool,

    /// If just interacted (right click).
    pub interacted: bool,

    /// If just jumped.
    pub jumped: bool,

    /// Raw local movement intention derived from the player directional keys,
    /// normalized.  X is interpreted as left/right, Z is interpreted as
    /// forward/back.
    ///
    /// This is always XZ, but could be extended to include Y in the future.
    pub movement: Vec3f,

    /// How much to offset the selected block index by.
    pub cycle_block_off: i16,
}

impl InputState {
    pub fn from_input(inp: &Gd<Input>) -> Self {
        let attacked = inp.is_action_just_pressed("player_attack".into());
        let interacted = inp.is_action_just_pressed("player_interact".into());
        let jumped = inp.is_action_just_pressed("move_jump".into());

        let movement = {
            let vec = inp.get_vector(
                "move_left".into(),
                "move_right".into(),
                "move_forward".into(),
                "move_backward".into(),
            );

            if vec.length() > MOVE_ACTIVATION_THRESH {
                let vec_norm = vec.normalized();
                Vec3f::new_xz(vec_norm.x as f32, vec_norm.y as f32)
            } else {
                Vec3f::zero()
            }
        };

        let cycle_block_off = if inp.is_action_just_pressed("player_cycle_block".into()) {
            1
        } else {
            0
        };

        Self {
            attacked,
            interacted,
            jumped,
            movement,
            cycle_block_off,
        }
    }
}

/// Context about the player state needed to interpret the actions they took.
pub struct InputContext {
    camera_pos: Vec3f,
    facing_vec: Vec3f,
    // TODO stuff with this
}
